home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / C / Comet2.1.3.cpt / Comet / serial.c < prev    next >
Text File  |  1991-10-30  |  14KB  |  700 lines

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3. */
  4.  
  5. #include <em.h>
  6.  
  7. #include <serial.h>
  8. #include <3270.h>
  9. #include <h19.h>
  10. #include <errors.h>
  11. #include <config.h>
  12. #include <menudefs.h>
  13. #include <osutil.h>
  14.  
  15. /* defines for serial port xon/xoff */
  16. #define SHUTOFF        1600
  17. #define SERBUFSIZE    4096
  18.  
  19. /* modemport menu items in serial version */
  20.  
  21. #define MODEMPORT    1
  22. #define PRINTERPORT    2
  23. #define NUMPORTS    2
  24.  
  25. int fdcapture = -1;         /* fd for transfer file */
  26.  
  27. char * aserinbuf;            /* input buffer to assign to Modem port */
  28. char * bserinbuf;            /* ditto for printer port */
  29. char * readbuf;             /* our read buffer */
  30.     /* buffers for serial reads */
  31.  
  32. char xoffmess[] = "No XON/XOFF--Capture may lose text";
  33.  
  34. int noserd;                    /* SERD serial driver resource not present */
  35.  
  36.  
  37. struct winds * modembusy;            /* port in use flag */
  38. struct winds * printerbusy;
  39.  
  40. short modemopened;            /* port was opened flag */
  41. short printopened;
  42.  
  43. #define baud38400    1
  44.  
  45. int baudrates[] = {baud57600, baud38400, baud19200, baud9600, baud4800, baud2400, baud1200, baud300};
  46. int dataconst[] = {data8, data7, data6};
  47.     /* 5, 6, 7, 8 data bits */
  48. int parityconst[] = {noParity, evenParity, oddParity};
  49.     /* none, even, odd */
  50. int stopconst[] = {stop20, stop15, stop10};
  51.     /* 1, 1.5, 2 stop bits */
  52.  
  53. extern Handle menu[];
  54.  
  55. /*  check the serial port for fresh data 
  56.     uses emdp by default 
  57. */
  58.  
  59. serial_service()
  60. {
  61.     long readcnt;
  62.     long sercnt;
  63.     
  64.     if (!emdp->connopen)
  65.         return;
  66.         
  67.     SerGetBuf(emdp->refin, &sercnt);
  68.  
  69.     if (noserd) {
  70.         /* if the SERD is not present we must do xon/xoff handling */
  71.         
  72.         if (emdp->xon) {
  73.             if (sercnt > SHUTOFF) {
  74.                 /* turn it off */
  75.                 serputchar(X_OFF);
  76.                 emdp->xon = FALSE;
  77.             }
  78.         }
  79.         else if (sercnt < SHUTOFF) {
  80.             /* turn transmission back on */
  81.             serputchar(X_ON);
  82.             emdp->xon = TRUE;
  83.         }
  84.     }
  85.     if (sercnt) {
  86.         register char * readp;
  87.         register char * bufend;
  88.  
  89.         if (emdp->icon_up)
  90.             emalert();            /* highlight icon to show activity */
  91.  
  92.         if (sercnt > SERBUFSIZE) {
  93.             readcnt = SERBUFSIZE;
  94.         }
  95.         else {
  96.             readcnt = sercnt;
  97.         }
  98.         FSRead(emdp->refin, &readcnt, readbuf);
  99. #ifdef USESERIALWAIT
  100.         if (autokey || readcnt <= 1)
  101.             serialwait = 0;
  102.         else
  103.             serialwait = 0;
  104.             /* wait for i ticks to service serial again */
  105. #endif
  106.  
  107.         emdp->in_cnt += readcnt;
  108.         if ( emdp->in_cnt >= 1000 ) {
  109.             /* turn the kilochar counter over */
  110.             emdp->in_cnt = 0;
  111.             emdp->kin_cnt++;
  112.             drawincount();
  113.         }
  114.         
  115.         for (readp = readbuf, bufend = readp + readcnt; readp < bufend; readp++) {
  116.             /* mash the high bit down for the emulator */
  117.             *readp &= 0x7f;
  118.         }
  119.         (*emdp->emstr)(readbuf, (unsigned short) readcnt);
  120.         if (readcnt <= 3 || autokey || autokeypersist) {
  121.             /* if the user is holding a key down, make sure the cursor shows */
  122.             setcursor();
  123.             if (autokey && autokeywait != NULL) {
  124.                 autokeypersist = TRUE;
  125.                 tm_tset(60, clrautokeywait, NULL, autokeywait);
  126.             }
  127.         }
  128.         
  129.         emdp->hycnewdata = TRUE;
  130.  
  131. #ifdef SERFILECAPTURE
  132.     /* an old feature we will probably support at a higher level */
  133.         if (fdcapture >= 0) {
  134.             char * stake;
  135.  
  136.             for (stake = readp = readbuf; readp < bufend; readp++) {
  137.                 if (*readp == LF) {
  138.                     write(fdcapture, stake, readp - stake); 
  139.                         /* skip the LF */
  140.                     stake = readp + 1;
  141.                 }
  142.             }
  143.             if (readp > stake)
  144.                 /* write out what's left */
  145.                 write(fdcapture, stake, readp - stake); 
  146.         }
  147. #endif
  148.     }
  149. }
  150.  
  151.  
  152. char seropenerr[] = "Not enough memory to open Serial Driver";
  153.  
  154. openserport()
  155. {
  156.     OSErr result;
  157.     char leaveDTRup;
  158.     struct winds * thedp;
  159.     
  160.     thedp = emdp;
  161.     if (readbuf == NULL) {
  162.         readbuf = malloc(SERBUFSIZE);
  163.         if (readbuf == NULL) {
  164.             return(-1);
  165.         }
  166.     }
  167.     if (emdp->refin)
  168.         /* don't open twice */
  169.         return(0);
  170.  
  171.     if (emdp->usebport) {
  172.         /* use the Printer Port */
  173.         if (printerbusy) {
  174.             if (queryserclose(printerbusy)) {
  175.                 closeconn(printerbusy);
  176.                 getcontext(thedp);        /* restore our context */
  177.             }
  178.             else
  179.                 return(-1);
  180.         }
  181.         if (bserinbuf == NULL) {
  182.             bserinbuf = malloc(SERBUFSIZE);
  183.             if (bserinbuf == NULL) {
  184.                 error(&seropenerr[0]);
  185.                 return(-1);
  186.             }
  187.         }
  188.         emdp->refin = -8;
  189.         emdp->refout = -9;
  190.     }
  191.     else {
  192.         /* use the Modem Port */
  193.         if (modembusy) {
  194.             if (queryserclose(modembusy)) {
  195.                 closeconn(modembusy);
  196.                 getcontext(thedp);        /* restore our context */
  197.             }
  198.             else
  199.                 return(-1);
  200.         }
  201. #ifdef OMNITEST
  202.         if (omni_test()) {
  203.             /* verify that the Omninet driver is not mucking around with the port */
  204.             porterr(0);
  205.             return(-1);
  206.         }
  207. #endif
  208.         if (aserinbuf == NULL) {
  209.             aserinbuf = malloc(SERBUFSIZE);
  210.             if (aserinbuf == NULL) {
  211.                 error(&seropenerr[0]);
  212.                 return(-1);
  213.             }
  214.         }
  215.         emdp->refin = -6;
  216.         emdp->refout = -7;
  217.     }
  218.     if ((result =  RAMSDOpen(emdp->usebport ? sPortB : sPortA)) != noErr ) {
  219.         /* open failed */
  220.         if (result == openErr) {
  221.             noserd = TRUE;
  222.             error("No SERD resource available; using manual XON/XOFF");
  223.             if ((result = OpenDriver(emdp->usebport ? "\P.BOut" : "\P.AOut", &emdp->refout) ) ) {
  224.                 porterr(result);
  225.                 return(-1);
  226.             }
  227.         }
  228.         else {
  229.             /* (result == portInUse || result == portNotCf) don't cover all bases! */
  230.             porterr(result);
  231.             return(-1);
  232.         }
  233.     }
  234.     else {
  235.         /* make the SERD do XON/XOFF */
  236.         SerShk serShk;
  237.     
  238.         noserd = FALSE;
  239.  
  240.         if (emdp->baud > baud38400) {
  241.         /* use XON/XOFF at speeds < 38,400 baud */
  242.             
  243.             serShk.fXOn = (Byte) TRUE;            /* output XON-XOFF on/off */
  244.             serShk.fCTS = (Byte) FALSE;            /* CTS output off */
  245.             serShk.xOn  = (char) CTLQ;            /* xon char DC1 */
  246.             serShk.xOff = (char) CTLS;            /* xoff char DC3 */
  247.             serShk.errs = (Byte) 0;                /* input abort settings    ALL = 0160 */
  248.             serShk.evts = (Byte) 0;                /* status junk     */
  249.             serShk.fInX = (Byte) TRUE;            /* input XON-XOFF on/off */
  250.             serShk.null = (Byte) FALSE;            /* CTS input off */
  251.         
  252.             if (Control(emdp->refout, _newrom() ? 14 : 10, &serShk))
  253.                 error(xoffmess);
  254.                 /* "Advanced" control call, dups SerHShake adding DTR input as 8th byte,
  255.                     used when not old ROM */
  256.         }
  257.         /* make control call so Mac + will leave its DTR line asserted when you close driver */
  258.         if (_newrom()) {
  259.             leaveDTRup = 0x80;    /* mash bit 7 down for DTR */
  260.             Control(emdp->refout, 16, &leaveDTRup);
  261.         }
  262.     }
  263.     SerSetBuf(emdp->refin, emdp->usebport ? bserinbuf : aserinbuf, SERBUFSIZE);
  264.  
  265.     if (emdp->usebport) {
  266.         printerbusy = emdp;
  267.         printopened = TRUE;
  268.     }
  269.     else {
  270.         modembusy = emdp;
  271.         modemopened = TRUE;
  272.     }
  273.     
  274.     sermenuset();
  275.     
  276.     if (setupport())
  277.         return(-1);
  278.         
  279.     emdp->xon = TRUE;
  280.     emdp->ucb.u_sendm = EVERYC;        /* asciitoken--send promptly */
  281.  
  282.     tickserial = cticks + 2;
  283.     if (tickserial == 0)
  284.         tickserial++;
  285.         /* start up tick counter for service */
  286.         
  287.     return(0);
  288. }
  289.  
  290.  
  291. setupport()
  292. {
  293.     int serconf;
  294.  
  295.     if (!emdp->refin)
  296.         return(-1);
  297.  
  298.     serconf = 0;
  299.     serconf = emdp->baud 
  300.                 | emdp->parity 
  301.                 | emdp->stop 
  302.                 | emdp->data;
  303.     
  304.     if (SerReset(emdp->refout, serconf) || SerReset(emdp->refin, serconf)) {
  305.         error("Can't configure serial port");
  306.         return(-1);
  307.     }
  308.     return(0);
  309. }
  310.  
  311.  
  312.  
  313. localconfig()
  314. {
  315.     Handle hconfig;
  316.     struct serconfig * confp;
  317.  
  318.     if ((hconfig = Get1Resource('CONF', SERCONFID)) == (Handle) NULL) {
  319.         /* no configuration resource exists */
  320.  
  321.         emdp->usebport = NOPORT;
  322.  
  323.         emdp->baud = baud9600;
  324.         emdp->parity = noParity;
  325.         emdp->stop = stop20;
  326.         emdp->data = data8;
  327.         emdp->data = data8;
  328.         
  329.         /* wait until user desires to open driver */
  330.     }
  331.     else {
  332.         confp = (struct config *) *hconfig; 
  333.  
  334.         emdp->usebport = confp->cport;
  335.         
  336.         emdp->baud = confp->cbaud;
  337.         emdp->parity = confp->cparity;
  338.         emdp->stop = confp->cstop;
  339.         emdp->data = confp->cdata;
  340.  
  341.         ReleaseResource(hconfig);
  342.     }
  343. }
  344.  
  345.  
  346. setlocalconfig()
  347. {
  348.     struct serconfig * confp;
  349.     Handle hconfig;
  350.  
  351.     if ((hconfig = Get1Resource('CONF', SERCONFID)) != NULL) {
  352.         /* kill current version */
  353.         RmveResource(hconfig);
  354.         UpdateResFile(emdp->resfid);
  355.         DisposHandle(hconfig);
  356.     }
  357.     /* add new resource */
  358.     hconfig = NewHandle((Size) sizeof(struct serconfig));
  359.     if (hconfig == NULL) {
  360.         error("Out of memory");
  361.         return(-1);
  362.     }
  363.         
  364.     AddResource(hconfig, 'CONF', SERCONFID, "\P");
  365.     if (ResError()) {
  366.         error("Can't create CONF 1 resource");
  367.         return(-1);
  368.     }
  369.  
  370.     /* set it */
  371.     HLock(hconfig);
  372.  
  373.     confp = (struct config *) *hconfig; 
  374.     confp->cport = emdp->usebport;
  375.     confp->cbaud = emdp->baud;
  376.     confp->cparity = emdp->parity;
  377.     confp->cstop = emdp->stop;
  378.     confp->cdata = emdp->data;
  379.  
  380.     HUnlock(hconfig);
  381.     ChangedResource(hconfig);
  382.     UpdateResFile(emdp->resfid); 
  383.     if (ResError()) {
  384.         error("No serial configuration update");
  385.         return(-1);
  386.     }
  387.     ReleaseResource(hconfig);
  388. }
  389.  
  390.  
  391. porterr(code)
  392. int code;
  393. {
  394.     emdp->refin = emdp->refout = 0;
  395.     if (emdp->usebport)
  396.         error("The Printer Port can't be used--is AppleTalk off?");
  397.     else
  398.         error("The Modem Port can't be used");
  399. }
  400.  
  401.  
  402. closeserport(twp)
  403. struct winds * twp;
  404. {
  405.     if (!twp->refin)
  406.         return;
  407.         
  408.     if (twp->autohangup)
  409.         Control(twp->refout, 18, (Ptr) NULL);
  410.  
  411.     if (twp->usebport) {
  412.         if (!noserd)
  413.             RAMSDClose(sPortB);
  414.         else {
  415.             CloseDriver(twp->refout);
  416.         }
  417.         printerbusy = NULL;
  418.     }
  419.     else {
  420.         if (!noserd)
  421.             RAMSDClose(sPortA);
  422.         else {
  423.             CloseDriver(twp->refout);
  424.         }
  425.         modembusy = NULL;
  426.     }
  427.     twp->refin = twp->refout = 0;
  428. }
  429.  
  430.  
  431. omni_test()
  432. {
  433.     int refnum;
  434.  
  435.     if (!OpenDriver("\P.OmniDriver", &refnum)) {
  436.         CloseDriver(refnum);
  437.         return(TRUE);
  438.     }
  439.     else
  440.         return(FALSE);
  441. }
  442.  
  443.  
  444. /* put out a character */
  445.  
  446. serputchar(thechar)
  447. char thechar;
  448. {
  449.     long count = 1;
  450.  
  451.     if (!emdp->refout)
  452.         return(-1);
  453.  
  454.     serialwait = 0;
  455.  
  456.     FSWrite(emdp->refout, &count, &thechar);
  457.     ++emdp->out_cnt;
  458.     return(0);
  459. }
  460.  
  461.  
  462. /* update the counter, nothing else needed */
  463.  
  464. serputflush()
  465. {
  466.     drawoutcount();
  467. }
  468.  
  469.  
  470. sersendstr(strp)
  471. char * strp;
  472. {
  473.     long count;
  474.  
  475.     serialwait = 0;
  476.     
  477.     count = strlen(strp);
  478.     FSWrite(emdp->refout, &count, strp);
  479.     emdp->out_cnt += count;
  480.     drawoutcount();
  481. }
  482.  
  483.  
  484. /* send a block */
  485.  
  486. sersendcount(strp, strcount)
  487. char * strp;
  488. short strcount;
  489. {
  490.     long count = strcount;
  491.  
  492.     serialwait = 0;
  493.     
  494.     FSWrite(emdp->refout, &count, strp);
  495.     emdp->out_cnt += count;
  496.     drawoutcount();
  497. }
  498.  
  499.  
  500. sersendBreak()
  501. {
  502.     long ticks;
  503.  
  504.     SerSetBrk(emdp->refout);
  505.     Delay((long) 30, &ticks);
  506.     SerClrBrk(emdp->refout);
  507. }
  508.  
  509.  
  510. /* routines follow to handle menus that control the serial port */
  511.  
  512. menuserial(theItem)
  513. short theItem;
  514. {
  515.     /* reset data, parity, and stop bit settings */
  516.     
  517.     if (theItem == SERPORTRESET) {
  518.         SysPtr    sysparam;
  519.         
  520.         sysparam = GetSysPPtr();
  521.         if (emdp->usebport)
  522.             sysparam->valid &= 0xFFFFFFF0;    /* blank out Printer Port configuration */
  523.         else
  524.             sysparam->valid &= 0xFFFFFF0F;    /* blank out Modem Port configuration */
  525.  
  526.         if (WriteParam())                /* save the reset configuration */
  527.             error("Couldn't update parameter RAM");
  528.         return(TRUE);
  529.     }
  530.     else if (theItem == SERPORTHANGUP) {
  531.         serhangup(keydp);
  532.         return(TRUE);
  533.     }
  534.     else if (theItem == SERAUTOHANG) {
  535.         keydp->autohangup = !keydp->autohangup;
  536.         keydp->confchanged = TRUE;
  537.         CheckItem(menu[SERIALMENU], SERAUTOHANG, keydp->autohangup ? (Boolean) TRUE : (Boolean) FALSE);
  538.         return(TRUE);
  539.     }
  540.     
  541.     getcontext(keydp);
  542.     
  543.     switch (theItem) {
  544.         case SERSENDHIER: {
  545.             /* should be hierarchical, for now is sytek escape */
  546.             (*emdp->putchar)(CTLA);
  547.             (*emdp->putchar)(CTLB);
  548.             return(TRUE);
  549.         }
  550.         case BAUD57600:
  551.         case BAUD38400:
  552.         case BAUD19200:
  553.         case BAUD9600:
  554.         case BAUD4800:
  555.         case BAUD2400:
  556.         case BAUD1200:
  557.         case BAUD300:
  558.         {
  559.             emdp->baud = baudrates[theItem - BAUD57600];
  560.             break;
  561.         }
  562.         case DATA6: {
  563.             emdp->data = data6;
  564.             break;
  565.         }
  566.         case DATA7: {
  567.             emdp->data = data7;
  568.             break;
  569.         }
  570.         case DATA8: {
  571.             emdp->data = data8;
  572.             break;
  573.         }
  574.         case PARITYNONE: {
  575.             emdp->parity = noParity;
  576.             break;
  577.         }
  578.         case PARITYEVEN: {
  579.             emdp->parity = evenParity;
  580.             break;
  581.         }
  582.         case PARITYODD: {
  583.             emdp->parity = oddParity;
  584.             break;
  585.         }
  586.         case STOP1: {
  587.             emdp->stop = stop10;
  588.             break;
  589.         }
  590.         case STOP1HALF: {
  591.             emdp->stop = stop15;
  592.             break;
  593.         }
  594.         case STOP2: {
  595.             emdp->stop = stop20;
  596.             break;
  597.         }
  598.         default: {
  599.             return(TRUE);
  600.         }
  601.     }
  602.     keydp->confchanged = TRUE;
  603.     sermenuset();
  604.     setupport();
  605.     return(FALSE);
  606. }
  607.  
  608.  
  609. sermenuset()
  610. {
  611.     int count;
  612.  
  613.     CheckItem(menu[SERIALMENU], SERAUTOHANG, emdp->autohangup ? (Boolean) TRUE : (Boolean) FALSE);
  614.  
  615.     /* blank exclusive items out */
  616.  
  617.     for (count = BAUD57600; count <= STOP1; count++) {
  618.         CheckItem(menu[SERIALMENU], count, FALSE);
  619.     }
  620.  
  621.     /* check baud rate */
  622.     for (count = 0; count < NUMBAUDS; count++) {
  623.         if (baudrates[count] == emdp->baud) {
  624.             CheckItem(menu[SERIALMENU], count + BAUD57600, TRUE);
  625.         }
  626.     }
  627.  
  628.     /* check data bits */
  629.     for (count = 0; count < DATAITEMS; count++) {
  630.         if (dataconst[count] == emdp->data) {
  631.             CheckItem(menu[SERIALMENU], count + DATA8, TRUE);
  632.             break;
  633.         }
  634.     }
  635.  
  636.     /* check parity bits */
  637.     for (count = 0; count < PARITYITEMS; count++) {
  638.         if (parityconst[count] == emdp->parity) {
  639.             CheckItem(menu[SERIALMENU], count + PARITYNONE, TRUE);
  640.             break;
  641.         }
  642.     }
  643.  
  644.     /* check stop bits */
  645.     for (count = 0; count < STOPITEMS; count++) {
  646.         if (stopconst[count] == emdp->stop) {
  647.             CheckItem(menu[SERIALMENU], count + STOP2, TRUE);
  648.             break;
  649.         }
  650.     }
  651. }
  652.  
  653.  
  654. /* hang up the phone line(s); close will cause DTR to drop */
  655.  
  656. sercleanup()
  657. {
  658.     short refnum;
  659.     
  660.     if (noserd) {
  661.         if (modemopened) {
  662.             OpenDriver("\P.AOut", &refnum);
  663.             CloseDriver(refnum);
  664.         }
  665.         if (printopened) {
  666.             OpenDriver("\P.BOut", &refnum);
  667.             CloseDriver(refnum);
  668.         }
  669.     }
  670.     else {
  671.         if (modemopened) {
  672.             RAMSDOpen(sPortA);
  673.             RAMSDClose(sPortA);
  674.         }
  675.         if (printopened) {
  676.             RAMSDOpen(sPortA);
  677.             RAMSDClose(sPortB);
  678.         }
  679.     }
  680. }
  681.  
  682.  
  683. /* hangup the phone line by dropping DTR */
  684.  
  685. serhangup(twp)
  686. struct winds * twp;
  687. {
  688.     if (twp->refout) {
  689.         Control(twp->refout, 18, (Ptr) NULL);
  690.     }
  691.     else {
  692.         /* driver is closed, reopen & THEN hang it up */
  693.         getcontext(twp);
  694.         openserport();
  695.         Control(twp->refout, 18, (Ptr) NULL);
  696.         closeserport(twp);
  697.     }
  698. }
  699.  
  700.